#pragma once

namespace SortDetail
{
	template <typename MapTy>
	using MapK = typename MapTy::K;
	template <typename MapTy>
	using MapIt = typename MapTy::Iter;
	template <typename MapTy>
	using ItemList = std::list<MapIt<MapTy>>;
	template <typename MapTy>
	using ItemListIt = typename ItemList<MapTy>::iterator;

	template <typename MapTy>
	struct Sub;
	template <typename MapTy>
	using SubList = std::list<Sub<MapTy>>;
	template <typename MapTy>
	using SubListIt = typename SubList<MapTy>::iterator;

	template <typename MapTy>
	struct Item
	{
		MapIt<MapTy> _dataIt;
		SubListIt<MapTy> _subIt;
		ItemListIt<MapTy> _itemIt;
		virtual size_t getSort() const = 0;
		virtual std::ostream& fillOs(std::ostream& os) const { return os << "[" << getSort() << "]"; }
	};

	template <typename MapTy>
	struct Sub
	{
		size_t _id;
		SubListIt<MapTy> _subIt;
		ItemList<MapTy> _list;
	};
}

template <typename MapTy>
struct Sort
{
	MapTy& _data;
	SortDetail::SubList<MapTy> _list;

	Sort(MapTy& data) : _data(data) {}
	auto update(SortDetail::MapIt<MapTy> it, bool ret) -> bool;

	auto pushSubBack(size_t itemK, SortDetail::SubListIt<MapTy> it) -> SortDetail::SubListIt<MapTy>;
	auto pushSubFront(size_t itemK, SortDetail::SubListIt<MapTy> it) -> SortDetail::SubListIt<MapTy>;
	auto moveItem2Sub(SortDetail::Item<MapTy>* pItem, SortDetail::SubListIt<MapTy> it) -> bool;
	auto fillOs(std::ostream& os, bool (*check)(const SortDetail::Item<MapTy>&) = NULL) const -> std::ostream&;
};

#include "SortImpl.h"